#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <sys/epoll.h>
#include <unistd.h>
#include <netinet/in.h>

#define MAX_LENGTH 1024

int main(int argc, char * * argv)
{
	int sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == sockfd)
	{
		perror("socket:");
		exit(-1);
	}

	struct sockaddr_in server_addr;
	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(4396);
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	int ret = bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
	if(-1 == ret)
	{
		perror("bind:");
		exit(-1);
	}
	if(-1 == listen(sockfd, 10))
	{
		perror("listen:");
		close(sockfd);
		exit(-1);
	}

	int epfd = epoll_create(1);
	struct epoll_event ev, events[MAX_LENGTH];
	ev.events = EPOLLIN;
	ev.data.fd = sockfd;
	epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ev);
	
	while(1)
	{
		int nready = epoll_wait(epfd, events, MAX_LENGTH, -1);
		char buffer[128] = {0};
		ssize_t count;
		for(int i = 0; i < nready; i ++)
		{
			int connfd = events[i].data.fd;
			if(sockfd == connfd)
			{
				struct sockaddr_in client_addr;
				socklen_t len = sizeof(client_addr);
				int clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &len);
				if(-1 == clientfd)
				{
					perror("accept:");
					close(sockfd);
					exit(-1);
				}
				ev.data.fd = clientfd;
				ev.events = EPOLLIN;
				epoll_ctl(epfd, EPOLL_CTL_ADD, clientfd, &ev);
			}
			else if (events[i].events & EPOLLIN)
			{
				count = recv(connfd, buffer, sizeof(buffer), 0);
				if(0 == count)
				{
					printf("disconnected\n");
					epoll_ctl(epfd, EPOLL_CTL_DEL, connfd, NULL);
					close(connfd);
					continue;
				}
				printf("clientfd: %d, count: %ld, buffer: %s\n", connfd, count, buffer);
				send(connfd, buffer, count, 0);
			}
		}
	}

	
	close(sockfd);
	exit(0);
}





